package com.lxf.cloudcar.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.lxf.cloudcar.bean.UserCarBean;
import com.lxf.cloudcar.mapper.UserCarItemRepository;
import com.lxf.cloudcar.mapper.UserCarMapper;
import com.lxf.cloudcar.service.UserCarService;
import com.lxf.cloudfeign.client.productClient.ProductClient;
import com.lxf.cloudfeign.client.userClient.UserClient;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 罗兴发
 * @data 2025/7/29 14:52
 * @description：购物车-业务实现层
 */
@Service
@Slf4j
public class UserCarServiceImpl implements UserCarService {

    @Resource
    UserCarMapper userCarMapper;

    @Resource
    private UserClient userClient;

    @Resource
    private ProductClient productClient;

    @Resource
    UserCarItemRepository userCarItemRepository;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Resource
    private RedisConnectionFactory redisConnectionFactory;

    /**
     * 添加进购物车
     * @param json
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addCar(JSONObject json, HttpServletRequest request) {
        JSONObject js = new JSONObject();

        //获取请求凭证,凭证中存放用户ID和用户名，存放格式为：userId_userName
        String secretToken = request.getHeader("secretToken");

        JSONObject j1 = new JSONObject();
        j1.put("redis_key",secretToken);
        j1.put("name","商品");
        //获取redis中缓存的token
        String o = userClient.getRedisData(j1);
        if (null!=o){
            // 截取请求头中存储的用户ID
            int secretTokenIndex = secretToken.lastIndexOf(":");
            String userIdSub = secretToken.substring(secretTokenIndex+1);
            Integer userId = Integer.valueOf(userIdSub);//用户ID

            // 获取前端传递的参数
            String goodCode = json.getString("good_code");//商品编码
            Integer goodNum = json.getInteger("good_num");//商品数量

            JSONObject j4 = new JSONObject();
            j4.put("redis_key",goodCode);

            //从redis中根据商品编码查询商品库存信息（必须保证编码的唯一性）
            String s = userClient.getRedisData(j4);

            //商品剩余数量
            Integer nums = Integer.valueOf(s);

            // 若是库存不足，则无法添加到购物车
            if (goodNum<=nums){
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String addTime = sf.format(new Date());
                //查询商品详情信息接口
                JSONObject j = new JSONObject();
                j.put("good_code",goodCode);
                String product = productClient.getProductByCode(j);

                //数据转换
                JSONObject object = JSONObject.parseObject(product);

                //根据商品编码查询到的商品详情信息
                JSONObject data = object.getJSONObject("data");
                String goodName = data.getString("goodName");
                log.info("商品详情信息：",data);

                // 根据商品编码查询购物车
                UserCarBean userCarBean = userCarMapper.getCarByGoodCode(goodCode,userId);
                if (null==userCarBean){
                    // 对象实例化
                    UserCarBean car = new UserCarBean();
                    car.setUserId(userId);
                    car.setAddTime(addTime);
                    car.setGoodCode(goodCode);
                    car.setGoodNum(goodNum);
                    car.setGoodName(goodName);

                    // list封装
                    List<UserCarBean> list = new ArrayList<>();
                    list.add(car);

                    // 添加购物车商品
                    int flag = userCarMapper.addCar(list);
                    if (flag<0){
                        js.put("code",401);
                        js.put("msg","Fails");
                    }else {
                        js.put("code",200);
                        js.put("msg","Success");

                        // es存储
                        userCarItemRepository.save(car);
                    }
                }else {
                    // 购物车中商品的数量
                    Integer num = userCarBean.getGoodNum();

                    Integer carId = userCarBean.getCarId();

                    // 新的数量
                    Integer newNum = num + goodNum;

                    // 新增购物车商品数量
                    int flag = userCarMapper.updateCarNumById(carId,newNum);
                    if (flag<0){
                        js.put("code",401);
                        js.put("msg","Fails");
                    }else {
                        js.put("code",200);
                        js.put("msg","Success");

                        //更新es中的数据存储
                        UserCarBean car = userCarMapper.getCarById(carId);
                        userCarItemRepository.save(car);

                        log.info("更新购物车商品数量成功！");
                    }
                }
            }else {
                js.put("code",401);
                js.put("msg","The Goods Number Is Lack");
            }
        }else {
            js.put("code",400);
            js.put("msg","The Current Request is Invalid");
        }
        return JSONObject.toJSONString(js, SerializerFeature.WriteMapNullValue);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String delCarById(JSONObject json, HttpServletRequest request) {
        JSONObject js = new JSONObject();
        //获取请求凭证,凭证中存放用户ID和用户名，存放格式为：userId_userName
        String secretToken = request.getHeader("secretToken");

        JSONObject j1 = new JSONObject();
        j1.put("redis_key",secretToken);
        j1.put("name","商品");
        //获取redis中缓存的token
        String o = userClient.getRedisData(j1);
        if (null!=o){
            // 获取前端传递的参数
            Integer carId = json.getInteger("car_id");//购物车条目ID
            int flag = userCarMapper.delCarById(carId);
            if (flag<0){
                js.put("code",401);
                js.put("msg","Fails");
            }else {
                js.put("code",200);
                js.put("msg","Success");
                //删除es中的数据
                userCarItemRepository.deleteById(String.valueOf(carId));
            }
        }else {
            js.put("code",400);
            js.put("msg","The Current Request is Invalid");
        }
        return JSONObject.toJSONString(js, SerializerFeature.WriteMapNullValue);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateCarNumById(JSONObject json, HttpServletRequest request) {
        JSONObject js = new JSONObject();
        //获取请求凭证,凭证中存放用户ID和用户名，存放格式为：userId_userName
        String secretToken = request.getHeader("secretToken");

        JSONObject j1 = new JSONObject();
        j1.put("redis_key",secretToken);
        j1.put("name","商品");
        //获取redis中缓存的token
        String o = userClient.getRedisData(j1);
        if (null!=o){
            // 获取前端传递的参数
            Integer carId = json.getInteger("car_id");//购物车条目ID
            Integer goodNum = json.getInteger("good_num");//商品数量

            //更新信息
            int flag = userCarMapper.updateCarNumById(carId, goodNum);
            if (flag<0){
                js.put("code",401);
                js.put("msg","Fails");
            }else {
                js.put("code",200);
                js.put("msg","Success");
                //更新es中的数据
                UserCarBean car = userCarMapper.getCarById(carId);
                userCarItemRepository.save(car);
            }
        }else {
            js.put("code",400);
            js.put("msg","The Current Request is Invalid");
        }
        return JSONObject.toJSONString(js, SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String getCarLikeName(JSONObject json, HttpServletRequest request) {
        JSONObject js = new JSONObject();
        //获取请求凭证,凭证中存放用户ID和用户名，存放格式为：userId_userName
        String secretToken = request.getHeader("secretToken");

        JSONObject j1 = new JSONObject();
        j1.put("redis_key",secretToken);
        j1.put("name","商品");
        //获取redis中缓存的token
        String o = userClient.getRedisData(j1);
        if (null!=o){
            // 获取前端传递的参数
            String goodName = json.getString("good_name");//商品数量
            Integer page = json.getInteger("page");
            Integer size = json.getInteger("size");

            //计算初始页
            Integer startPage = (page-1)*size;

            // 1. 构建查询条件
            NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder()
                    .withQuery(QueryBuilders.multiMatchQuery(goodName, "goodName"))
                    .withPageable(PageRequest.of(startPage, size));

            // 2. 添加高亮配置
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("goodName")
                    .preTags("<span style='color:red'>")
                    .postTags("</span>");
            queryBuilder.withHighlightBuilder(highlightBuilder);

            // 3. 执行查询
            SearchHits<UserCarBean> hits = elasticsearchRestTemplate
                    .search(queryBuilder.build(), UserCarBean.class);

            // 4. 处理高亮结果
            List<UserCarBean> list = hits.stream()
                    .map(hit -> {
                        UserCarBean doc = hit.getContent();
                        Map<String, List<String>> highlightFields = hit.getHighlightFields();
                        highlightFields.forEach((field, texts) -> {
                            try {
                                Field declaredField = doc.getClass().getDeclaredField(field);
                                declaredField.setAccessible(true);
                                declaredField.set(doc, texts.get(0));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        });
                        return doc;
                    }).collect(Collectors.toList());
            // 7. 构造分页结果
            PageImpl<UserCarBean> userCarBeans = new PageImpl<>(list, PageRequest.of(startPage, size), hits.getTotalHits());

            js.put("data",userCarBeans);
            js.put("code",200);
            js.put("msg","Success");
        }else {
            js.put("code",400);
            js.put("msg","The Current Request is Invalid");
        }
        return JSONObject.toJSONString(js, SerializerFeature.WriteMapNullValue);
    }

    @Override
    public String deleteCarAllEs() {
        userCarItemRepository.deleteAll();
        return "Success";
    }
}
